module Cal

importall Ela, Res

abstract Analysis
abstract LinearAnalysis <: Analysis
abstract StaticLinearAnalysis <: LinearAnalysis
abstract DynamicLinearAnalysis <: LinearAnalysis
# abstract EigenAnalysis <: LinearAnalysis

export Analysis, 
        LinearAnalysis, EigenAnalysis, 
        execAnalysis, saveResult

type EigenAnalysis <: LinearAnalysis
    
    domain::Domain
    nMode::Int64
    res::Vector{EigenResult}

    norm::String 

    function EigenAnalysis(domain::Domain)

        nMode = domain.nDof
        res = [EigenResult(domain,i) for i in 1:nMode]
        norm = "Norm" #// "Disp","Mass"
        return new(domain,nMode,res,norm)

    end

    function EigenAnalysis(domain::Domain,nMode::Int64,norm::String="Norm")

        if nMode > domain.nDof
            nMode = domain.nDof
        end

        res = [EigenResult(domain,i) for i in 1:nMode]
        return new(domain,nMode,res,norm)

    end

end

function execAnalysis(analysis::EigenAnalysis,prt::Bool=true)

    linalgsys = analysis.domain.linalgsys

    if analysis.nMode == analysis.domain.nDof
        Res = eig(linalgsys.K,linalgsys.M)
    else
        Res = eigs(linalgsys.K,linalgsys.M;
                    nev=analysis.nMode,which=:SM)
    end

    Omega = Res[1]
    Mode = Res[2]

    for i in 1:analysis.nMode
        res = analysis.res[i]
        res.omega = sqrt(Omega[i])
        res.freq = res.omega/6.2831853
        if i == 1
            println("========================================")
            println("========= Eigen Analysis Result ========")
            println("========================================")
            @printf("%8s    %12s    %12s\n","order","omega(rad/s)","freq(Hz)")
            printResult(res)
        elseif i == analysis.nMode
            printResult(res)
            println("========================================")
        else
            printResult(res)
        end        

        modalShape = Mode[:,i]
        normFactor = 1.
        if analysis.norm == "Disp"
            normFactor = 1./maximum(abs(mode))
        elseif analysis.norm == "Mass"
            Meq = modalShape.'*analysis.domain.linalgsys.M*modalShape
            normFactor = 1./sqrt(Meq)
        end
        res.modalShape = normFactor.*modalShape
    end

end

function saveResult(analysis::EigenAnalysis,fmt::String="gmsh")

    for i in 1:analysis.nMode
        res = analysis.res[i]
        setDomain(res)
        saveResult(res,fmt)
    end

end

end